<script setup lang="ts">
import type Node from "element-plus/es/components/tree/src/model/node";
import { cloneDeep } from "@pureadmin/utils";
import { nextTick, onMounted, reactive, ref } from "vue";
import {
  Search,
  Grid,
  RefreshLeft,
  Download,
  Plus,
  Edit,
  Delete
} from "@element-plus/icons-vue";
import type { DeptItem, ResultUser } from "@/api/system";
import {
  getDeptList,
  getUserList,
  getDictData,
  getJobList,
  getRoleList,
  getCurrentLevel,
  addUserApi,
  getDeptFilter,
  editUserApi,
  delUserApi,
  exportUserList,
  resetPwdApi
} from "@/api/system";
import { getVppUserListAll } from "@/api/vppUser";
import {
  ElTree,
  ElTable,
  ElForm,
  ElNotification,
  ElMessageBox
} from "element-plus";
import { isvalidPhone } from "@/utils/validate.js";
import { downloadFile } from "@/utils/index";
import { useUserStoreHook } from "@/store/modules/user";
const { user } = useUserStoreHook();
const treeRef = ref<InstanceType<typeof ElTree>>();
const ruleForm = ref<InstanceType<typeof ElForm>>();
const inputSearch = async () => {
  let data: any = await getDeptData(
    undefined,
    deptSearch.value ? deptSearch.value : undefined
  );
  deptDatas.data = data;
};
const vppUserAll = ref([]);
const getAllUser = () => {
  return new Promise(async resolve => {
    let data = await getVppUserListAll();
    resolve(data);
  });
};
const props = {
  label: "label",
  hasChildren: "hasChildren",
  children: "children",
  isLeaf: "leaf"
};
const getDeptData = (pid: number | undefined, name: string | undefined) => {
  return new Promise(async (resolve, reject) => {
    let { content } = await getDeptList({
      sort: "id,desc",
      pid: pid ?? undefined,
      name: name ?? undefined
    });
    resolve(content);
  });
};
const loadNode = async (node: Node, resolve: any) => {
  if (status.value === "edit" && !node.data.id) {
    return resolve([]);
  } else {
    let data = await getDeptData(node?.data?.id, undefined);
    return resolve(data);
  }
};
const deptSearch = ref("");
const deptDatas = reactive({
  data: []
});
const queryForm = reactive({
  data: {
    blurry: undefined,
    createTime: [],
    enabled: undefined
  }
});
const resetQuery = () => {
  queryForm.data = {
    blurry: undefined,
    createTime: [],
    enabled: undefined
  };
};
const statusDict = reactive({
  data: []
});
const jobList = reactive({
  data: []
});
const roleData = reactive({
  data: []
});
const currentLevel = ref(3);
const init = async () => {
  const { content } = await getDictData({
    dictName: "user_status",
    page: 0,
    size: 9999
  });
  vppUserAll.value = await getAllUser();
  const jobData = await getJobList({ page: 0, size: 9999, enabled: true });
  const resRoleData = await getRoleList();
  roleData.data = resRoleData;
  jobList.data = jobData.content;
  statusDict.data = content;
  const { level } = await getCurrentLevel();
  currentLevel.value = level;
};
init();
const nameFormat = v => {
  if (v) {
    let item = vppUserAll.value.find(i => i.id === v);
    return item ? item.name : "";
  } else {
    return "";
  }
};
const colums = reactive({
  data: [
    {
      label: "账号名",
      prop: "username"
    },
    {
      label: "昵称",
      prop: "nickName"
    },
    {
      label: "性别",
      prop: "gender"
    },
    {
      label: "电话",
      prop: "phone"
    },
    {
      label: "邮箱",
      prop: "email",
      width: "200px"
    },
    {
      label: "部门",
      prop: "dept.name"
    },
    {
      label: "虚拟电厂用户",
      prop: "vppUserId"
    },
    {
      label: "状态",
      prop: "enabled"
    },
    {
      label: "创建日期",
      prop: "createTime",
      width: "200px"
    }
  ]
});
const defaultColums = reactive({
  data: [
    {
      label: "账号名",
      prop: "username"
    },
    {
      label: "昵称",
      prop: "nickName"
    },
    {
      label: "性别",
      prop: "gender"
    },
    {
      label: "电话",
      prop: "phone"
    },
    {
      label: "邮箱",
      prop: "email",
      width: "200px"
    },
    {
      label: "部门",
      prop: "dept.name"
    },
    {
      label: "虚拟电厂用户",
      prop: "vppUserId"
    },
    {
      label: "状态",
      prop: "enabled"
    },
    {
      label: "创建日期",
      prop: "createTime",
      show: true,
      width: "200px"
    }
  ]
});
const pageObj = reactive({
  data: {
    currentPage: 1,
    pageSize: 10,
    total: 0
  }
});
const switchChange = row => {
  ElMessageBox.confirm(
    `此操作将 "${!row.enabled ? "禁用" : "启用"}" ${row.username}, 是否继续?`,
    "系统提示",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
      dangerouslyUseHTMLString: true,
      draggable: true
    }
  )
    .then(async () => {
      await editUserApi(row);
      ElNotification({
        title: "系统提示",
        message: !row.enabled ? "禁用成功" : "激活成功",
        type: "success"
      });
      search();
    })
    .catch(() => {
      tableData.data.forEach(i => {
        if (i.id === row.id) {
          i.enabled = !i.enabled;
        }
      });
    });
};
const handleSizeChange = () => {
  search();
};
const handleCurrentChange = async () => {
  getList();
};
const search = async () => {
  pageObj.data.currentPage = 1;
  let { content, totalElements } = await getUser();
  pageObj.data.total = totalElements;
  tableData.data = content;
};
const getList = async () => {
  let { content, totalElements } = await getUser();
  pageObj.data.total = totalElements;
  tableData.data = content;
};
const tableData = reactive({
  data: []
});
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
const multipleSelection = ref([]);
const handleSelectionChange = val => {
  multipleSelection.value = val;
};
const loading = ref(false);
const activeDeptId = ref("");
const getUser = () => {
  loading.value = true;
  return new Promise<ResultUser>(async (resolve, reject) => {
    let data = await getUserList({
      current: pageObj.data.currentPage,
      size: pageObj.data.pageSize,
      sort: "id,desc",
      deptId: activeDeptId.value ? activeDeptId.value : undefined,
      blurry: queryForm.data.blurry ? queryForm.data.blurry : undefined,
      enabled: queryForm.data.enabled ? queryForm.data.enabled : undefined,
      createTime: queryForm.data.createTime.length
        ? queryForm.data.createTime
        : undefined
    });
    loading.value = false;
    resolve(data);
  });
};
const selectableFunc = (row, index) => {
  return !(row.username === "admin");
};
const nodeClick = node => {
  activeDeptId.value = node.id;
  search();
};

const queryShow = ref(true);

const checkAll = ref(true);
const isIndeterminate = ref(false);
const checkedCities = ref([]);

const handleCheckAllChange = (val: boolean) => {
  checkedCities.value = val ? defaultColums.data.map(item => item.prop) : [];
  isIndeterminate.value = false;
  if (checkedCities.value.length) {
    colums.data = defaultColums.data;
  } else {
    colums.data = [];
  }
};
const handleCheckedCitiesChange = (value: string[]) => {
  const checkedCount = value.length;
  checkAll.value = checkedCount === defaultColums.data.length;
  isIndeterminate.value =
    checkedCount > 0 && checkedCount < defaultColums.data.length;
  let cols = [];
  defaultColums.data.forEach(i => {
    if (value.indexOf(i.prop) > -1) {
      cols.push(i);
    }
  });
  colums.data = cols;
};
onMounted(() => {
  search();
  checkedCities.value = colums.data.map(item => item.prop);
});
const validPhone = (rule, value, callback) => {
  if (!value) {
    callback(new Error("请输入电话号码"));
  } else if (!isvalidPhone(value)) {
    callback(new Error("请输入正确的11位手机号码"));
  } else {
    callback();
  }
};
const keydown = e => {
  if (e.keyCode === 32) {
    e.returnValue = false;
  }
};

const form = reactive({
  data: {
    vppUserId: undefined,
    id: null,
    username: undefined,
    phone: undefined,
    nickName: undefined,
    email: undefined,
    jobs: undefined,
    gender: undefined,
    enabled: undefined,
    roles: undefined,
    dept: {
      id: undefined
    }
  },
  rules: {
    username: [
      { required: true, message: "请输入账号名", trigger: "blur" },
      { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" }
    ],
    nickName: [
      { required: true, message: "请输入账号昵称", trigger: "blur" },
      { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" }
    ],
    email: [
      { required: true, message: "请输入邮箱地址", trigger: "blur" },
      { type: "email", message: "请输入正确的邮箱地址", trigger: "blur" }
    ],
    phone: [{ required: true, trigger: "blur", validator: validPhone }]
  }
});
const resetForm = () => {
  ruleForm.value.resetFields();
};
const addDialog = ref(false);
const title = ref("新增账号");
const status = ref("add");
const addUser = () => {
  addDialog.value = true;
  title.value = "新增账号";
  status.value = "add";
  form.data = {
    vppUserId: undefined,
    id: null,
    username: undefined,
    phone: undefined,
    nickName: undefined,
    email: undefined,
    jobs: undefined,
    gender: "男",
    enabled: "false",
    roles: undefined,
    dept: {
      id: undefined
    }
  };
  resetForm();
};
const beforeClose = d => {
  form.data = {
    vppUserId: undefined,
    id: null,
    username: undefined,
    phone: undefined,
    nickName: undefined,
    email: undefined,
    jobs: undefined,
    gender: undefined,
    enabled: undefined,
    roles: undefined,
    dept: {
      id: undefined
    }
  };
  nextTick(() => {
    d();
  });
};
const deptDataFormInner = reactive({
  data: []
});
const editRow = async row => {
  let data = cloneDeep(row);
  data.jobs = data.jobs.map(i => i.id);
  data.roles = data.roles.map(i => i.id);
  form.data = data;
  addDialog.value = true;
  title.value = "编辑账号";
  status.value = "edit";
  let res = await getDeptFilter([row.dept.id], { exclude: "false" });
  deptDataFormInner.data = res.content;
};
const editSelect = () => {
  if (multipleSelection.value.length === 1) {
    editRow(multipleSelection.value[0]);
  }
};
const resetPwd = () => {
  if (multipleSelection.value.length) {
    ElMessageBox.confirm(
      `你选中了${multipleSelection.value.length}位账号，确认重置账号的密码吗?`,
      "系统提示",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        dangerouslyUseHTMLString: true,
        draggable: true
      }
    ).then(async () => {
      await resetPwdApi(multipleSelection.value.map(i => i.id));
      ElNotification({
        title: "系统提示",
        message: "重置成功, 账号新密码:123456",
        type: "success"
      });
      search();
    });
  }
};
const delSelect = () => {
  if (multipleSelection.value.length) {
    ElMessageBox.confirm(
      `确认删除选中的${multipleSelection.value.length}条数据?`,
      "系统提示",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        dangerouslyUseHTMLString: true,
        draggable: true
      }
    ).then(async () => {
      await delUserApi(multipleSelection.value.map(i => i.id));
      ElNotification({
        title: "系统提示",
        message: "删除成功",
        type: "success"
      });
      search();
    });
  }
};
const exportData = async () => {
  let res = await exportUserList({
    current: pageObj.data.currentPage,
    size: pageObj.data.pageSize,
    sort: "id,desc",
    deptId: activeDeptId.value ? activeDeptId.value : undefined,
    blurry: queryForm.data.blurry ? queryForm.data.blurry : undefined,
    enabled: queryForm.data.enabled ? queryForm.data.enabled : undefined,
    createTime: queryForm.data.createTime.length
      ? queryForm.data.createTime
      : undefined
  });
  downloadFile(res, "账号数据", "xlsx");
};
const delConfirm = async row => {
  await delUserApi([row.id]);
  ElNotification({
    title: "系统提示",
    message: "删除成功",
    type: "success"
  });
  search();
};
const nodeClickTwo = node => {
  form.data.dept.id = node.id;
};
const cancel = () => {
  form.data = {
    vppUserId: undefined,
    id: null,
    username: undefined,
    phone: undefined,
    nickName: undefined,
    email: undefined,
    jobs: undefined,
    gender: undefined,
    enabled: undefined,
    roles: undefined,
    dept: {
      id: undefined
    }
  };
  ruleForm.value.resetFields();
  nextTick(() => {
    addDialog.value = false;
  });
};
const submit = async () => {
  ruleForm.value.validate(async valid => {
    if (valid) {
      let data = cloneDeep(form.data);
      data.roles = data.roles.map(i => {
        return {
          id: i
        };
      });
      data.jobs = data.jobs.map(i => {
        return {
          id: i
        };
      });
      if (status.value === "add") {
        await addUserApi(data);
        ElNotification({
          title: "系统提示",
          message: "账号创建成功，初始密码为123456",
          type: "success"
        });
      } else {
        await editUserApi(data);
        ElNotification({
          title: "系统提示",
          message: "编辑成功",
          type: "success"
        });
      }
      resetForm();
      nextTick(() => {
        addDialog.value = false;
        search();
      });
    }
  });
};
</script>

<template>
  <div class="flex justify-between h-[calc(100%-29px)]">
    <div class="w-[190px]">
      <div class="width-full">
        <el-input
          v-model="deptSearch"
          v-optimize:throttle="{
            event: 'input',
            fn: inputSearch,
            timeout: 1000
          }"
          placeholder="输入部门名称搜索"
          :prefix-icon="Search"
        />
      </div>
      <div class="width-full py-[12px]">
        <el-tree
          ref="treeRef"
          :expand-on-click-node="false"
          :data="deptDatas.data"
          :props="props"
          :load="loadNode"
          lazy
          @node-click="nodeClick"
        >
          <template #default="{ node, data }">
            <span class="custom-tree-node">
              <span :class="[data.id === activeDeptId ? 'font-bold' : '']">{{
                node.label
              }}</span>
            </span>
          </template>
        </el-tree>
      </div>
    </div>
    <div class="w-[calc(100%-200px)]">
      <div v-if="queryShow" class="mb-[10px] w-full search-form">
        <el-form :inline="true" :model="queryForm.data" label-width="0px">
          <el-form-item>
            <el-input
              v-model="queryForm.data.blurry"
              clearable
              placeholder="输入名称或邮箱搜索"
            />
          </el-form-item>
          <el-form-item>
            <el-date-picker
              v-model="queryForm.data.createTime"
              type="datetimerange"
              range-separator=":"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="YYYY-MM-DD HH:mm:ss"
            />
          </el-form-item>
          <el-form-item>
            <el-select
              v-model="queryForm.data.enabled"
              placeholder="状态"
              clearable
              style="width: 120px"
            >
              <el-option
                v-for="item in statusDict.data"
                :key="item.value"
                :value="item.value"
                :label="item.label"
              />
            </el-select>
          </el-form-item>
          <el-form-item class="ml-[10px]">
            <el-button type="primary" :icon="Search" @click="search"
              >搜索</el-button
            >
            <el-button :icon="RefreshLeft" @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
      <div class="w-full">
        <div class="w-full flex justify-between">
          <div class="buttons flex align-center">
            <el-button type="primary" :icon="Plus" @click="addUser"
              >新增</el-button
            >
            <el-button
              type="success"
              :icon="Edit"
              :disabled="!(multipleSelection.length === 1)"
              @click="editSelect"
              >修改</el-button
            >
            <el-button
              type="danger"
              :icon="Delete"
              :disabled="!multipleSelection.length"
              @click="delSelect"
              >删除</el-button
            >
            <el-button type="warning" :icon="Download" @click="exportData"
              >导出</el-button
            >
            <el-button
              type="primary"
              :icon="RefreshLeft"
              :disabled="!multipleSelection.length"
              @click="resetPwd"
              >重置密码</el-button
            >
          </div>
          <div class="settings">
            <el-button-group class="ml-4">
              <el-button
                type="primary"
                :icon="Search"
                @click="queryShow = !queryShow"
              />
              <el-button type="primary" :icon="RefreshLeft" @click="getList" />
              <el-popover placement="bottom" :width="200" trigger="click">
                <template #reference>
                  <el-button type="primary" :icon="Grid" />
                </template>
                <el-checkbox
                  v-model="checkAll"
                  :indeterminate="isIndeterminate"
                  @change="handleCheckAllChange"
                  >全选</el-checkbox
                >
                <el-checkbox-group
                  v-model="checkedCities"
                  class="columns-show-group"
                  @change="handleCheckedCitiesChange"
                >
                  <el-checkbox
                    v-for="item in defaultColums.data"
                    :key="item.prop"
                    :label="item.prop"
                    >{{ item.label }}</el-checkbox
                  >
                </el-checkbox-group>
              </el-popover>
            </el-button-group>
          </div>
        </div>
        <div v-loading="loading" class="w-full mt-[10px]">
          <el-table
            ref="multipleTableRef"
            :data="tableData.data"
            style="width: 100%"
            @selection-change="handleSelectionChange"
          >
            <el-table-column
              :selectable="selectableFunc"
              type="selection"
              width="55"
            />
            <el-table-column
              v-for="item in colums.data"
              :key="item.prop"
              :prop="item.prop"
              :label="item.label"
              :width="item.width"
            >
              <template #default="scope">
                <template v-if="item.prop === 'enabled'">
                  <el-switch
                    v-model="scope.row.enabled"
                    :disabled="scope.row.username === 'admin'"
                    @change="switchChange(scope.row)"
                  />
                </template>
                <template v-if="item.prop === 'vppUserId'">
                  <div>{{ nameFormat(scope.row.vppUserId) }}</div>
                </template>
              </template>
            </el-table-column>
            <el-table-column fixed="right" label="操作" width="120">
              <template #default="scope">
                <el-button
                  type="primary"
                  size="small"
                  :icon="Edit"
                  @click="editRow(scope.row)"
                />
                <el-popconfirm
                  width="200px"
                  title="确定删除本条数据吗？"
                  @confirm="delConfirm(scope.row)"
                >
                  <template #reference>
                    <el-button type="danger" size="small" :icon="Delete" />
                  </template>
                </el-popconfirm>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <div class="page w-full mt-[10px]">
          <el-pagination
            v-model:current-page="pageObj.data.currentPage"
            v-model:page-size="pageObj.data.pageSize"
            :page-sizes="[10, 20, 30, 40, 50, 100]"
            layout="total, sizes, prev, pager, next, jumper"
            :total="pageObj.data.total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </div>
      </div>
    </div>
    <el-dialog
      v-model="addDialog"
      :close-on-click-modal="false"
      :before-close="beforeClose"
      :title="title"
      width="40%"
    >
      <el-form
        ref="ruleForm"
        label-width="180px"
        label-position="top"
        :model="form.data"
        :rules="form.rules"
      >
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="账号名" prop="username">
              <el-input v-model="form.data.username" @keydown="keydown" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="电话" prop="phone">
              <el-input v-model.number="form.data.phone" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="昵称" prop="nickName">
              <el-input v-model="form.data.nickName" @keydown="keydown" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="邮箱" prop="email">
              <el-input v-model="form.data.email" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="部门" prop="dept.id">
              <el-tree-select
                v-model="form.data.dept.id"
                :expand-on-click-node="false"
                :data="deptDataFormInner.data"
                nodeKey="id"
                lazy
                :load="loadNode"
                :props="props"
                @node-click="nodeClickTwo"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="岗位" prop="jobs">
              <el-select
                v-model="form.data.jobs"
                multiple
                placeholder="请选择"
                collapse-tags
                collapse-tags-tooltip
              >
                <el-option
                  v-for="item in jobList.data"
                  :key="item.name"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="性别">
              <el-radio-group v-model="form.data.gender">
                <el-radio label="男">男</el-radio>
                <el-radio label="女">女</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="状态">
              <el-radio-group
                v-model="form.data.enabled"
                :disabled="form.data.id === user.id"
              >
                <el-radio
                  v-for="item in statusDict.data"
                  :key="item.id"
                  :label="item.value"
                  >{{ item.label }}</el-radio
                >
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="角色" prop="roles">
              <el-select
                v-model="form.data.roles"
                multiple
                placeholder="请选择"
                collapse-tags
                collapse-tags-tooltip
              >
                <el-option
                  v-for="item in roleData.data"
                  :key="item.name"
                  :disabled="!(item.level < currentLevel)"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="虚拟电厂用户" prop="vppUserId">
              <el-select
                v-model="form.data.vppUserId"
                :disabled="form.data.username === 'admin'"
                placeholder="请选择"
                clearable
              >
                <el-option
                  v-for="item in vppUserAll"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="submit"> 确认 </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
:deep(.el-dropdown-menu__item i) {
  margin: 0;
}

:deep(.el-button:focus-visible) {
  outline: none;
}

.main-content {
  //margin: 24px 24px 0 !important;
}

.search-form {
  :deep(.el-form-item) {
    margin-right: 4px;
    margin-bottom: 0;
  }
}
</style>
